package gae.testjig.client;

import gae.testjig.client.ChannelProvider.ChannelReady;
import gae.testjig.client.ChannelProvider.ClientChannel;
import gae.testjig.client.UIFeedbackLabel.FeedbackListener;
import gae.testjig.client.eventbus.EchoEvent;
import gae.testjig.client.eventbus.ChannelMetaEvent;
import gae.testjig.client.eventbus.InfoEvent;
import gae.testjig.client.eventbus.TestStatusEvent;

import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiConstructor;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.SimpleEventBus;

public class UIQueueTxTest extends Composite {
	
	interface UIAdminActionsUiBinder extends UiBinder<Widget, UIQueueTxTest> {}
	private static UIAdminActionsUiBinder uiBinder = GWT.create(UIAdminActionsUiBinder.class);
	
	@UiField Button btnEchoChannel;
	@UiField Button btnGetTestStatus;
	@UiField Button btnStartTest1;
	@UiField Button btnStartTest2;
	@UiField Button btnStartTest3;
	@UiField Button btnClearLog;
	@UiField UIFeedbackLabel lblFeedback;
	@UiField HTML txtConsoleLog;
	@UiField UITestStatus uiTestStatus;
	
	private String testId = "";

	@UiConstructor
	public UIQueueTxTest(final GaeTestJigServiceAsync SERVICE, final ClientChannel cp, SimpleEventBus eventBus) {
		initWidget(uiBinder.createAndBindUi(this));
		
		ChannelMetaEvent.register(eventBus, new ChannelMetaEvent.Handler() {
			@Override
			public void onFeedback(String message) {
				lblFeedback.setTextNoSpin(message);
			}
		});
		EchoEvent.registerToSource(eventBus, cp.getClientChannelId(), new EchoEvent.Handler() {
			@Override
			public void onEcho(EchoEvent event) {
				lblFeedback.setTextNoSpin(event.getMessage());
			}
		});
		InfoEvent.registerToSource(eventBus, cp.getClientChannelId(), new InfoEvent.Handler() {
			@Override
			public void onInfo(InfoEvent event) {
				lblFeedback.setTextNoSpin(event.getMessage());
			}
		});
		TestStatusEvent.registerToSource(eventBus, cp.getClientChannelId(), new TestStatusEvent.Handler() {
			@Override
			public void onEvent(TestStatusEvent event) {
				uiTestStatus.setInvocations(uiTestStatus.getInvocations()+event.getInvocations());
				uiTestStatus.setRetries(uiTestStatus.getRetries()+event.getRetries());
				uiTestStatus.setMismatches(uiTestStatus.getMismatches()+event.getMismatches());
			}
		});
		
		lblFeedback.addFeedbackListener(new FeedbackListener() {
			@Override
			public void onFeedback(String message) {
				append(message);
			}
		});
		
		btnStartTest1.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				cp.ensureOpenChannel(new ChannelReady() {
					@Override
					public void onChannelReady() {
						AsyncCallback<String> callback = new AsyncCallback<String>() {
							@Override
							public void onFailure(Throwable caught) {
								lblFeedback.setTextNoSpin(caught.getMessage());
							}
							@Override
							public void onSuccess(String testId) {
								lblFeedback.setTextNoSpin("Test 1 was started and given a testId="+testId);
								UIQueueTxTest.this.testId = testId;
							}
						};
						uiTestStatus.reset();
						lblFeedback.setTextAndSpin("starting test 1...");
						SERVICE.startTest1(cp.getClientChannelId(), callback);
					}
				});
			}
		});
		
		btnStartTest2.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				cp.ensureOpenChannel(new ChannelReady() {
					@Override
					public void onChannelReady() {
						AsyncCallback<String> callback = new AsyncCallback<String>() {
							@Override
							public void onFailure(Throwable caught) {
								lblFeedback.setTextNoSpin(caught.getMessage());
							}
							@Override
							public void onSuccess(String testId) {
								lblFeedback.setTextNoSpin("Test 2 was started and given a testId="+testId);
								UIQueueTxTest.this.testId = testId;
							}
						};
						uiTestStatus.reset();
						lblFeedback.setTextAndSpin("starting test 2...");
						SERVICE.startTest2(cp.getClientChannelId(), callback);
					}
				});
			}
		});

		btnStartTest3.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				cp.ensureOpenChannel(new ChannelReady() {
					@Override
					public void onChannelReady() {
						AsyncCallback<String> callback = new AsyncCallback<String>() {
							@Override
							public void onFailure(Throwable caught) {
								lblFeedback.setTextNoSpin(caught.getMessage());
							}
							@Override
							public void onSuccess(String testId) {
								lblFeedback.setTextNoSpin("Test 3 was started and given a testId="+testId);
								UIQueueTxTest.this.testId = testId;
							}
						};
						uiTestStatus.reset();
						lblFeedback.setTextAndSpin("starting test 3...");
						SERVICE.startTest3(cp.getClientChannelId(), callback);
					}
				});
			}
		});

		btnGetTestStatus.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				if ( UIQueueTxTest.this.testId.length() == 0 ) {
					lblFeedback.setTextNoSpin("No test has been run yet.");
					return; // do nothing if no test has been run yet.
				}
				AsyncCallback<ClientTestStats> callback = new AsyncCallback<ClientTestStats>() {
					@Override
					public void onFailure(Throwable caught) {
						lblFeedback.setTextNoSpin(caught.getMessage());
					}
					@Override
					public void onSuccess(ClientTestStats stats) {
						lblFeedback.setTextNoSpin("current stats for testId="+stats.getTestId()+
								": invocationCount=" + stats.getInvocationCount() +
								", retryCount=" + stats.getRetryCount() +
								", state=" + stats.getState()
						);
					}
				};
				lblFeedback.setTextAndSpin("polling for test stats...");
				SERVICE.getTestStatus(UIQueueTxTest.this.testId, callback);
			}
		});
		
		btnEchoChannel.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				cp.ensureOpenChannel(new ChannelReady() {
					@Override
					public void onChannelReady() {
						AsyncCallback<Void> callback = new AsyncCallback<Void>() {
							@Override
							public void onFailure(Throwable caught) {
								lblFeedback.setTextNoSpin(caught.getMessage());
							}
							@Override
							public void onSuccess(Void v) {
							}
						};
						SERVICE.sendEchoChannel(cp.getClientChannelId(), callback);
					}
				});
			}
		});

		btnClearLog.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				clearLog();
			}
		});
	}
	
	public void append(List<String> list) {
		for ( String msg : list ) {
			append(msg);
		}
	}	
	
	public void append(String msg) {
		String content = txtConsoleLog.getHTML();
		txtConsoleLog.setHTML(content + msg + "<br/>");
		txtConsoleLog.getElement().setScrollTop(txtConsoleLog.getElement().getScrollHeight()); // keep scrolled to bottom
	}
	
	public void clearLog() {
		txtConsoleLog.setHTML("");
	}

}
